package com.zhuyuan.security.filter;

import com.zhuyuan.core.constant.Oauth2Constants;
import com.zhuyuan.core.exception.TokenException;
import com.zhuyuan.core.util.Convert;
import com.zhuyuan.redis.RedisService;
import com.zhuyuan.security.service.UserDetailsImpl;
import com.zhuyuan.system.api.domain.UserInfo;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;

/**
 * @Author: 张琳凯
 * @Description: 添加过滤器，获取token并解析出用户信息，并设置到SecurityContextHolder中
 * @DateTime: 2025/2/24 13:18
 **/
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private TokenStore tokenStore;
    private RedisService redisService;

    public JwtAuthenticationFilter(TokenStore tokenStore,RedisService redisService) {
        this.tokenStore = tokenStore;
        this.redisService=redisService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String token = extractToken(request);
        if (token != null) {
            Authentication authentication = getAuthentication(token);
            if (authentication != null) {
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(request, response);
    }

    private String extractToken(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }

    private Authentication getAuthentication(String token) {
        try {
            Map<String, Object> claims = tokenStore.readAccessToken(token).getAdditionalInformation();
            UserDetailsImpl userDetails = getUserDetails(claims);
            return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        } catch (Exception e) {
            return null;
        }
    }

    //通过解析token构建UserDetailsImpl
    private UserDetailsImpl getUserDetails(Map<String, Object> claims) {
        Long userId = Convert.toLong(claims.get("userId"));
        String userName = claims.get("userName").toString();
        //从redis中获取用户信息，在UserDetailServiceImpl中将信息存入redis中
        UserInfo userInfo=redisService.getCacheObject(Oauth2Constants.REDIS_USER_AUTHORITIES_CODE +userId);
        if (userInfo==null){
            //如果用户信息发生变化则删除缓存信息，返回token过期，重新获取用户信息
            throw new TokenException("用户信息已过期");
        }
//        String authStr= JSON.toJSONString(claims.get("authorities"));
//        List<String> strings = JSON.parseArray(authStr, String.class);
        Collection<? extends GrantedAuthority> authorityList = AuthorityUtils.createAuthorityList(cn.hutool.core.convert.Convert.toStrArray(userInfo.getPermissionList()));
        return new UserDetailsImpl(
                userId,
                userInfo,
                userName,
                "",
                true,
                true,
                true,
                true,
                authorityList);
    }
}